package net.worldscale.xp.wslib.wsxml.impl;

import java.util.Stack;
import net.worldscale.xp.wslib.wsxml.DomBuilder;
import net.worldscale.xp.wslib.wsxml.WsXML;
import net.worldscale.xp.wslib.wsxml.sax.IAttributes;
import net.worldscale.xp.wslib.wsxml.sax.ILocator;
import net.worldscale.xp.wslib.wsxml.sax.SaxException;
import net.worldscale.xp.wslib.wsxml.sax.SaxParseException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Text;

final class ImplDomBuilder extends DomBuilder {

    private Document mDOM;
    private final Stack<Element> mStack = new Stack<Element>();

    public ImplDomBuilder() {
    }

    @Override
    public Document getDOM() {
        return mDOM;
    }

    @Override
    public void characters(char[] ch, int start, int length) {
        final Text txt = mDOM.createTextNode(new String(ch, start, length));
        this.mStack.peek().appendChild(txt);
    }

    @Override
    public void endDocument() {
    }

    @Override
    public void endElement(String uri, String localName, String qName) throws SaxException {
        final Element ele = this.mStack.pop();
        if (!qName.equals(ele.getTagName())) {
            throw new SaxException("Element is not closed.");
        }
    }

    @Override
    public void endPrefixMapping(String prefix) {
    }

    @Override
    public void error(SaxParseException e) {
    }

    @Override
    public void fatalError(SaxParseException e) {
    }

    @Override
    public void ignorableWhitespace(char[] ch, int start, int length) {
    }

    @Override
    public void notationDecl(String name, String publicId, String systemId) {
    }

    @Override
    public void processingInstruction(String target, String data) {
    }

    @Override
    public void setDocumentLocator(ILocator locator) {
    }

    @Override
    public void skippedEntity(String name) {
    }

    @Override
    public void startDocument() {
        final Document doc = WsXML.getInstance().getDOMImplementation().createDocument(null, null, null);
        this.mDOM = doc;
    }

    @Override
    public void startElement(String uri, String localName, String qName,
            IAttributes attributes) {
        final Element newElement = this.mDOM.createElement(qName);
        if (attributes != null) {
            final int len = attributes.getLength();
            for (int i = 0; i < len; i++) {
                final String name, value;
                name = attributes.getQName(i);
                value = attributes.getValue(i);
                newElement.setAttribute(name, value);
            }
        }
        if (!this.mStack.isEmpty()) {
            this.mStack.peek().appendChild(newElement);
        } else {
            this.mDOM.appendChild(newElement);
        }
        this.mStack.push(newElement);
    }

    @Override
    public void startPrefixMapping(String prefix, String uri) {
    }

    @Override
    public void unparsedEntityDecl(String name, String publicId,
            String systemId, String notationName) {
    }

    @Override
    public void warning(SaxParseException e) {
    }
}
